﻿// Decompiled with JetBrains decompiler
// Type: TaleWorlds.CampaignSystem.Siege.SiegeEvent
// Assembly: TaleWorlds.CampaignSystem, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: E85F8C15-4DF6-4E9C-A58A-29177E40D07A
// Assembly location: D:\steam\steamapps\common\Mount & Blade II Bannerlord\bin\Win64_Shipping_Client\TaleWorlds.CampaignSystem.dll

using System;
using System.Collections.Generic;
using System.Linq;
using TaleWorlds.CampaignSystem.Actions;
using TaleWorlds.CampaignSystem.ComponentInterfaces;
using TaleWorlds.CampaignSystem.Encounters;
using TaleWorlds.CampaignSystem.GameMenus;
using TaleWorlds.CampaignSystem.MapEvents;
using TaleWorlds.CampaignSystem.Party;
using TaleWorlds.CampaignSystem.Settlements;
using TaleWorlds.Core;
using TaleWorlds.Library;
using TaleWorlds.SaveSystem;

#nullable disable
namespace TaleWorlds.CampaignSystem.Siege
{
  public class SiegeEvent
  {
    [SaveableField(6)]
    public readonly Settlement BesiegedSettlement;
    [SaveableField(10)]
    public readonly BesiegerCamp BesiegerCamp;
    [SaveableField(144)]
    private bool _isBesiegerDefeated;

    internal static void AutoGeneratedStaticCollectObjectsSiegeEvent(
      object o,
      List<object> collectedObjects)
    {
      ((SiegeEvent) o).AutoGeneratedInstanceCollectObjects(collectedObjects);
    }

    protected virtual void AutoGeneratedInstanceCollectObjects(List<object> collectedObjects)
    {
      collectedObjects.Add((object) this.BesiegedSettlement);
      collectedObjects.Add((object) this.BesiegerCamp);
      CampaignTime.AutoGeneratedStaticCollectObjectsCampaignTime((object) this.SiegeStartTime, collectedObjects);
    }

    internal static object AutoGeneratedGetMemberValueSiegeStartTime(object o)
    {
      return (object) ((SiegeEvent) o).SiegeStartTime;
    }

    internal static object AutoGeneratedGetMemberValueBesiegedSettlement(object o)
    {
      return (object) ((SiegeEvent) o).BesiegedSettlement;
    }

    internal static object AutoGeneratedGetMemberValueBesiegerCamp(object o)
    {
      return (object) ((SiegeEvent) o).BesiegerCamp;
    }

    internal static object AutoGeneratedGetMemberValue_isBesiegerDefeated(object o)
    {
      return (object) ((SiegeEvent) o)._isBesiegerDefeated;
    }

    public int SiegeWallSeed
    {
      get
      {
        return Common.GetDJB2("" + (object) this.SiegeStartTime.NumTicks + "*" + this.BesiegedSettlement.StringId + "*" + (object) (int) this.BesiegedSettlement.SettlementTotalWallHitPoints);
      }
    }

    public int SiegePeopleSeed
    {
      get
      {
        return Common.GetDJB2("" + (object) this.SiegeStartTime.NumTicks + "*" + this.BesiegedSettlement.StringId + "*" + (object) this.BesiegerCamp.NumberOfTroopsKilledOnSide + "#" + (object) this.BesiegedSettlement.NumberOfTroopsKilledOnSide);
      }
    }

    [SaveableProperty(5)]
    public CampaignTime SiegeStartTime { get; private set; }

    public bool IsPlayerSiegeEvent
    {
      get => this.BesiegerCamp.LeaderParty.IsMainParty || PlayerSiege.PlayerSiegeEvent == this;
    }

    public List<PartyBase> GetInvolvedPartiesForEventType(MapEvent.BattleTypes battleType)
    {
      List<PartyBase> partiesForEventType = new List<PartyBase>();
      foreach (PartyBase partyBase in this.BesiegerCamp.GetInvolvedPartiesForEventType(battleType))
        partiesForEventType.Add(partyBase);
      foreach (PartyBase partyBase in this.BesiegedSettlement.GetInvolvedPartiesForEventType(battleType))
        partiesForEventType.Add(partyBase);
      return partiesForEventType;
    }

    public MapEvent.BattleTypes GetCurrentBattleType()
    {
      return this.BesiegerCamp?.LeaderParty?.MapEvent != null ? this.BesiegerCamp.LeaderParty.MapEvent.EventType : MapEvent.BattleTypes.Siege;
    }

    public SiegeEvent(Settlement settlement, MobileParty besiegerParty)
    {
      this.BesiegedSettlement = settlement;
      this.BesiegedSettlement.SiegeEvent = this;
      this.BesiegerCamp = new BesiegerCamp(this);
      besiegerParty.BesiegerCamp = this.BesiegerCamp;
      if (besiegerParty.LeaderHero != null && settlement.OwnerClan != null && settlement.OwnerClan != Clan.PlayerClan)
        ChangeRelationAction.ApplyRelationChangeBetweenHeroes(settlement.OwnerClan.Leader, besiegerParty.LeaderHero, -5, besiegerParty.LeaderHero == Hero.MainHero);
      this.BesiegerCamp.InitializeSiegeEventSide();
      this.BesiegedSettlement.InitializeSiegeEventSide();
      this.SiegeStartTime = CampaignTime.Now;
      foreach (MobileParty mobileParty in (List<MobileParty>) MobileParty.All)
      {
        if (mobileParty.DefaultBehavior == AiBehavior.GoToSettlement && mobileParty.TargetSettlement == settlement && mobileParty.CurrentSettlement != settlement)
          mobileParty.Ai.SetMoveModeHold();
      }
      foreach (MobileParty party in (List<MobileParty>) settlement.Parties)
      {
        if (party.MapFaction == settlement.MapFaction && !party.IsMilitia && !party.IsGarrison && (party.DefaultBehavior != AiBehavior.GoToSettlement || party.TargetSettlement != settlement) && party.DefaultBehavior != AiBehavior.Hold)
          party.Ai.SetMoveGoToSettlement(party.CurrentSettlement);
      }
      this.BesiegedSettlement.Party.SetLevelMaskIsDirty();
      CampaignEventDispatcher.Instance.OnSiegeEventStarted(this);
    }

    public bool ReadyToBeRemoved => this.BesiegedSettlement.Party.SiegeEvent == null;

    public ISiegeEventSide GetSiegeEventSide(BattleSideEnum side)
    {
      return side != BattleSideEnum.Attacker ? (ISiegeEventSide) this.BesiegedSettlement : (ISiegeEventSide) this.BesiegerCamp;
    }

    public bool CanPartyJoinSide(PartyBase party, BattleSideEnum side)
    {
      IFaction partyFaction = party.MapFaction;
      BattleSideEnum side1 = BattleSideEnum.None;
      switch (side)
      {
        case BattleSideEnum.Defender:
          side1 = BattleSideEnum.Attacker;
          break;
        case BattleSideEnum.Attacker:
          side1 = BattleSideEnum.Defender;
          break;
      }
      return this.GetSiegeEventSide(side).GetInvolvedPartiesForEventType().All<PartyBase>((Func<PartyBase, bool>) (x => !x.MapFaction.IsAtWarWith(partyFaction))) & this.GetSiegeEventSide(side1).GetInvolvedPartiesForEventType().All<PartyBase>((Func<PartyBase, bool>) (x => x.MapFaction.IsAtWarWith(partyFaction)));
    }

    public void Tick(float dt)
    {
      if (CampaignTime.DeltaTime == CampaignTime.Zero || this.BesiegerCamp.LeaderParty.MapEvent != null || this.BesiegedSettlement.Party.MapEvent != null)
        return;
      this.TickSiegeEventSide((ISiegeEventSide) this.BesiegerCamp);
      this.TickSiegeEventSide((ISiegeEventSide) this.BesiegedSettlement);
    }

    private void TickSiegeEventSide(ISiegeEventSide siegeEventSide)
    {
      this.AdvanceStrategy(siegeEventSide);
      this.ConstructionTick(siegeEventSide);
      this.BombardTick(siegeEventSide);
    }

    public void OnBeforeSiegeEventEnd(BattleState winnerSide, MapEvent.BattleTypes battleType)
    {
      switch (battleType)
      {
        case MapEvent.BattleTypes.Siege:
        case MapEvent.BattleTypes.SiegeOutside:
          this._isBesiegerDefeated = winnerSide == BattleState.DefenderVictory;
          break;
        case MapEvent.BattleTypes.SallyOut:
          this._isBesiegerDefeated = winnerSide == BattleState.AttackerVictory;
          break;
      }
    }

    public void FinalizeSiegeEvent()
    {
      CampaignEventDispatcher.Instance.OnSiegeEventEnded(this);
      if (PlayerSiege.PlayerSiegeEvent == this)
        PlayerSiege.OnSiegeEventFinalized(this._isBesiegerDefeated);
      else if (PlayerSiege.PlayerSiegeEvent == null && MobileParty.MainParty.CurrentSettlement != null && MobileParty.MainParty.CurrentSettlement.SiegeEvent == this && !Hero.MainHero.IsPrisoner)
        GameMenu.SwitchToMenu(this._isBesiegerDefeated ? "siege_attacker_defeated" : "siege_attacker_left");
      this.BesiegerCamp.FinalizeSiegeEvent();
      this.BesiegedSettlement.FinalizeSiegeEvent();
      if (this.BesiegedSettlement.Party.MapEvent != null && !this.BesiegedSettlement.Party.MapEvent.IsSallyOut)
        this.BesiegedSettlement.Party.MapEvent.FinalizeEvent();
      if (this.BesiegedSettlement.Town != null && this.BesiegedSettlement.Town.GarrisonParty != null && this.BesiegedSettlement.Town.GarrisonParty.DefaultBehavior == AiBehavior.EngageParty)
        this.BesiegedSettlement.Town.GarrisonParty.Ai.SetMoveModeHold();
      if (this != PlayerSiege.PlayerSiegeEvent)
        return;
      PlayerSiege.ClosePlayerSiege();
    }

    public bool IsPartyInvolved(PartyBase party)
    {
      return this.GetInvolvedPartiesForEventType(this.GetCurrentBattleType()).Contains(party);
    }

    public void DoSiegeAction(
      ISiegeEventSide siegeEventSide,
      SiegeStrategyActionModel.SiegeAction siegeAction,
      SiegeEngineType siegeEngineType,
      int deploymentIndex,
      int reserveIndex)
    {
      SiegeEvent.SiegeEnginesContainer siegeEngines = siegeEventSide.SiegeEngines;
      switch (siegeAction)
      {
        case SiegeStrategyActionModel.SiegeAction.ConstructNewSiegeEngine:
          float siegeEngineHitPoints = Campaign.Current.Models.SiegeEventModel.GetSiegeEngineHitPoints(siegeEventSide.SiegeEvent, siegeEngineType, siegeEventSide.BattleSide);
          SiegeEvent.SiegeEngineConstructionProgress siegeEngine = new SiegeEvent.SiegeEngineConstructionProgress(siegeEngineType, 0.0f, siegeEngineHitPoints);
          siegeEngines.DeploySiegeEngineAtIndex(siegeEngine, deploymentIndex);
          this.BesiegedSettlement.Party.SetVisualAsDirty();
          break;
        case SiegeStrategyActionModel.SiegeAction.DeploySiegeEngineFromReserve:
          SiegeEvent.SiegeEngineConstructionProgress reservedSiegeEngine = siegeEngines.ReservedSiegeEngines[reserveIndex];
          siegeEngines.DeploySiegeEngineAtIndex(reservedSiegeEngine, deploymentIndex);
          this.BesiegedSettlement.Party.SetVisualAsDirty();
          break;
        case SiegeStrategyActionModel.SiegeAction.MoveSiegeEngineToReserve:
          siegeEngines.RemoveDeployedSiegeEngine(deploymentIndex, siegeEngineType.IsRanged, true);
          this.BesiegedSettlement.Party.SetVisualAsDirty();
          break;
        case SiegeStrategyActionModel.SiegeAction.RemoveDeployedSiegeEngine:
          siegeEngines.RemoveDeployedSiegeEngine(deploymentIndex, siegeEngineType.IsRanged, false);
          this.BesiegedSettlement.Party.SetVisualAsDirty();
          break;
        case SiegeStrategyActionModel.SiegeAction.Hold:
          break;
        default:
          throw new ArgumentOutOfRangeException();
      }
    }

    public void AdvanceStrategy(ISiegeEventSide siegeEventSide)
    {
      SiegeStrategyActionModel.SiegeAction siegeAction;
      SiegeEngineType siegeEngineType;
      int deploymentIndex;
      int reserveIndex;
      Campaign.Current.Models.SiegeStrategyActionModel.GetLogicalActionForStrategy(siegeEventSide, out siegeAction, out siegeEngineType, out deploymentIndex, out reserveIndex);
      this.DoSiegeAction(siegeEventSide, siegeAction, siegeEngineType, deploymentIndex, reserveIndex);
    }

    public void BreakSiegeEngine(ISiegeEventSide siegeEventSide, SiegeEngineType siegeEngineType)
    {
      if (siegeEngineType == DefaultSiegeEngineTypes.Preparations)
      {
        if (siegeEventSide.BattleSide != BattleSideEnum.Attacker)
          return;
        siegeEventSide.SiegeEngines.SiegePreparations.SetProgress(0.0f);
      }
      else if (siegeEngineType.IsRanged)
      {
        for (int index = siegeEventSide.SiegeEngines.DeployedRangedSiegeEngines.Length - 1; index >= 0; --index)
        {
          SiegeEvent.SiegeEngineConstructionProgress rangedSiegeEngine = siegeEventSide.SiegeEngines.DeployedRangedSiegeEngines[index];
          if (rangedSiegeEngine != null && rangedSiegeEngine.SiegeEngine == siegeEngineType && rangedSiegeEngine.IsActive)
          {
            siegeEventSide.SiegeEngines.RemoveDeployedSiegeEngine(index, true, false);
            this.BesiegedSettlement.Party.SetVisualAsDirty();
            break;
          }
        }
      }
      else
      {
        for (int index = siegeEventSide.SiegeEngines.DeployedMeleeSiegeEngines.Length - 1; index >= 0; --index)
        {
          SiegeEvent.SiegeEngineConstructionProgress meleeSiegeEngine = siegeEventSide.SiegeEngines.DeployedMeleeSiegeEngines[index];
          if (meleeSiegeEngine != null && meleeSiegeEngine.SiegeEngine == siegeEngineType && meleeSiegeEngine.IsActive)
          {
            siegeEventSide.SiegeEngines.RemoveDeployedSiegeEngine(index, false, false);
            this.BesiegedSettlement.Party.SetVisualAsDirty();
            break;
          }
        }
      }
    }

    public Dictionary<SiegeEngineType, int> GetPreparedSiegeEnginesAsDictionary(
      ISiegeEventSide siegeEventSide)
    {
      Dictionary<SiegeEngineType, int> enginesAsDictionary = new Dictionary<SiegeEngineType, int>();
      foreach (SiegeEvent.SiegeEngineConstructionProgress allSiegeEngine in siegeEventSide.SiegeEngines.AllSiegeEngines())
      {
        if (allSiegeEngine.IsActive && (double) allSiegeEngine.Hitpoints > 0.0 && allSiegeEngine.SiegeEngine != DefaultSiegeEngineTypes.Preparations)
        {
          if (enginesAsDictionary.ContainsKey(allSiegeEngine.SiegeEngine))
            ++enginesAsDictionary[allSiegeEngine.SiegeEngine];
          else
            enginesAsDictionary.Add(allSiegeEngine.SiegeEngine, 1);
        }
      }
      return enginesAsDictionary;
    }

    public List<MissionSiegeWeapon> GetPreparedAndActiveSiegeEngines(ISiegeEventSide siegeEventSide)
    {
      List<MissionSiegeWeapon> activeSiegeEngines = new List<MissionSiegeWeapon>();
      MBReadOnlyList<SiegeEvent.SiegeEngineConstructionProgress> deployedSiegeEngines = siegeEventSide.SiegeEngines.DeployedSiegeEngines;
      for (int index = 0; index < deployedSiegeEngines.Count; ++index)
      {
        SiegeEvent.SiegeEngineConstructionProgress constructionProgress = deployedSiegeEngines[index];
        if (constructionProgress.IsActive && (double) constructionProgress.Hitpoints > 0.0 && constructionProgress.SiegeEngine != DefaultSiegeEngineTypes.Preparations)
          activeSiegeEngines.Add(MissionSiegeWeapon.CreateCampaignWeapon(constructionProgress.SiegeEngine, index, constructionProgress.Hitpoints, constructionProgress.MaxHitPoints));
      }
      return activeSiegeEngines;
    }

    public void SetSiegeEngineStatesAfterSiegeMission(
      IEnumerable<IMissionSiegeWeapon> attackerMissionSiegeEngineData,
      IEnumerable<IMissionSiegeWeapon> defenderMissionSiegeEngineData)
    {
      this.SetSiegeEngineStatesForSiegeSide((ISiegeEventSide) this.BesiegerCamp, attackerMissionSiegeEngineData);
      this.SetSiegeEngineStatesForSiegeSide((ISiegeEventSide) this.BesiegedSettlement, defenderMissionSiegeEngineData);
    }

    private void SetSiegeEngineStatesForSiegeSide(
      ISiegeEventSide side,
      IEnumerable<IMissionSiegeWeapon> missionSiegeEngineData)
    {
      if (missionSiegeEngineData == null || !missionSiegeEngineData.Any<IMissionSiegeWeapon>())
        return;
      int index1 = missionSiegeEngineData.Count<IMissionSiegeWeapon>() - 1;
      MapEvent battle = PlayerEncounter.Battle;
      bool flag = battle != null && battle.IsSiegeAmbush;
      for (int index2 = side.SiegeEngines.DeployedSiegeEngines.Count - 1; index2 >= 0; --index2)
      {
        SiegeEvent.SiegeEngineConstructionProgress constructionProgress = side.SiegeEngines.DeployedSiegeEngines.ElementAt<SiegeEvent.SiegeEngineConstructionProgress>(index2);
        if (constructionProgress.IsActive)
        {
          IMissionSiegeWeapon missionSiegeWeapon = missionSiegeEngineData.ElementAt<IMissionSiegeWeapon>(index1);
          --index1;
          if (constructionProgress.SiegeEngine.IsRanged | flag && (double) missionSiegeWeapon.Health > 0.0)
            constructionProgress.SetHitpoints(missionSiegeWeapon.Health);
          else if (!flag || (double) missionSiegeWeapon.Health <= 0.0)
            this.BreakSiegeEngine(side, constructionProgress.SiegeEngine);
        }
      }
    }

    public void CreateSiegeObject(
      SiegeEvent.SiegeEngineConstructionProgress siegeEngineConstructionProgress,
      ISiegeEventSide siegeSide)
    {
      if (siegeEngineConstructionProgress.SiegeEngine.IsRanged)
        siegeEngineConstructionProgress.SetRangedSiegeEngine(new SiegeEvent.RangedSiegeEngine(siegeEngineConstructionProgress.SiegeEngine, siegeSide));
      SiegeEngineType siegeEngine = siegeEngineConstructionProgress.SiegeEngine;
      CampaignEventDispatcher.Instance.SiegeEngineBuilt(this, siegeSide.BattleSide, siegeEngine);
      this.BesiegedSettlement.Party.SetVisualAsDirty();
    }

    public override string ToString() => "Siege of " + (object) this.BesiegedSettlement.Name;

    public void ConstructionTick(ISiegeEventSide siegeEventSide)
    {
      SiegeEvent.SiegeEngineConstructionProgress siegeEngineConstructionProgress = (SiegeEvent.SiegeEngineConstructionProgress) null;
      if (siegeEventSide.SiegeEngines.SiegePreparations != null && !siegeEventSide.SiegeEngines.SiegePreparations.IsActive)
      {
        siegeEngineConstructionProgress = siegeEventSide.SiegeEngines.SiegePreparations;
      }
      else
      {
        foreach (SiegeEvent.SiegeEngineConstructionProgress deployedSiegeEngine in (List<SiegeEvent.SiegeEngineConstructionProgress>) siegeEventSide.SiegeEngines.DeployedSiegeEngines)
        {
          if (!deployedSiegeEngine.IsConstructed && !deployedSiegeEngine.IsBeingRedeployed)
          {
            siegeEngineConstructionProgress = deployedSiegeEngine;
            break;
          }
        }
      }
      if (siegeEngineConstructionProgress != null)
      {
        float num = Campaign.Current.Models.SiegeEventModel.GetConstructionProgressPerHour(siegeEngineConstructionProgress.SiegeEngine, this, siegeEventSide) * (float) CampaignTime.DeltaTime.ToHours;
        siegeEngineConstructionProgress.SetProgress(MBMath.ClampFloat(siegeEngineConstructionProgress.Progress + num, 0.0f, 1f));
        if (siegeEngineConstructionProgress.IsActive)
          this.CreateSiegeObject(siegeEngineConstructionProgress, siegeEventSide);
      }
      float num1 = 2f;
      foreach (SiegeEvent.SiegeEngineConstructionProgress deployedSiegeEngine in (List<SiegeEvent.SiegeEngineConstructionProgress>) siegeEventSide.SiegeEngines.DeployedSiegeEngines)
      {
        if (deployedSiegeEngine.IsConstructed && deployedSiegeEngine.IsBeingRedeployed)
        {
          float num2 = (float) (1.0 / (double) num1 * CampaignTime.DeltaTime.ToHours);
          deployedSiegeEngine.SetRedeploymentProgress(MBMath.ClampFloat(deployedSiegeEngine.RedeploymentProgress + num2, 0.0f, 1f));
          if (deployedSiegeEngine.IsActive)
            this.BesiegedSettlement.Party.SetVisualAsDirty();
        }
      }
      if (!siegeEventSide.SiegeEngines.ClearRemovedEnginesIfNecessary())
        return;
      this.BesiegedSettlement.Party.SetVisualAsDirty();
    }

    public void BombardTick(ISiegeEventSide siegeEventSide)
    {
      if (CampaignTime.DeltaTime == CampaignTime.Zero)
        return;
      SiegeEvent.SiegeEnginesContainer siegeEngines = this.GetSiegeEventSide(siegeEventSide.BattleSide.GetOppositeSide()).SiegeEngines;
      for (int index = 0; index < siegeEventSide.SiegeEngineMissiles.Count; ++index)
      {
        SiegeEvent.SiegeEngineMissile siegeEngineMissile = siegeEventSide.SiegeEngineMissiles[index];
        if (siegeEngineMissile.CollisionTime.IsPast && siegeEngineMissile.HitSuccessful)
        {
          switch (siegeEngineMissile.TargetType)
          {
            case SiegeBombardTargets.Wall:
              this.BesiegerCamp.BombardHitWalls(siegeEngineMissile.ShooterSiegeEngineType, siegeEngineMissile.TargetSlotIndex);
              continue;
            case SiegeBombardTargets.RangedEngines:
              SiegeEvent.SiegeEngineConstructionProgress rangedSiegeEngine = siegeEngines.DeployedRangedSiegeEngines[siegeEngineMissile.TargetSlotIndex];
              SiegeEvent.SiegeEngineConstructionProgress targetSiegeEngine = siegeEngineMissile.TargetSiegeEngine;
              if (rangedSiegeEngine != null && rangedSiegeEngine.IsActive && (double) rangedSiegeEngine.Hitpoints > 0.0)
              {
                this.BombardHitEngine(siegeEventSide, siegeEngineMissile.ShooterSiegeEngineType, rangedSiegeEngine);
                continue;
              }
              if (targetSiegeEngine != null && targetSiegeEngine != rangedSiegeEngine && (((IEnumerable<SiegeEvent.SiegeEngineConstructionProgress>) siegeEngines.DeployedRangedSiegeEngines).Contains<SiegeEvent.SiegeEngineConstructionProgress>(targetSiegeEngine) && targetSiegeEngine.IsActive || siegeEngines.ReservedSiegeEngines.Contains(targetSiegeEngine)))
              {
                this.BombardHitEngine(siegeEventSide, siegeEngineMissile.ShooterSiegeEngineType, targetSiegeEngine);
                continue;
              }
              continue;
            default:
              Debug.FailedAssert("Invalid target type on hit", "C:\\Develop\\MB3\\Source\\Bannerlord\\TaleWorlds.CampaignSystem\\Siege\\SiegeEvent.cs", nameof (BombardTick), 936);
              continue;
          }
        }
      }
      siegeEventSide.RemoveDeprecatedMissiles();
      foreach (SiegeEvent.SiegeEngineConstructionProgress deployedSiegeEngine in (List<SiegeEvent.SiegeEngineConstructionProgress>) siegeEventSide.SiegeEngines.DeployedSiegeEngines)
      {
        if (deployedSiegeEngine.IsActive)
        {
          SiegeEvent.SiegeEngineConstructionProgress attackerSiegeEngine = deployedSiegeEngine;
          SiegeEngineType siegeEngine = deployedSiegeEngine.SiegeEngine;
          SiegeEvent.RangedSiegeEngine rangedSiegeEngine = deployedSiegeEngine.RangedSiegeEngine;
          if (siegeEngine.IsRanged && rangedSiegeEngine != null && rangedSiegeEngine.IsReadyToFire)
          {
            rangedSiegeEngine.Reload();
            if ((double) attackerSiegeEngine.Hitpoints > 0.0)
            {
              int num = siegeEngine.IsRanged ? ((IReadOnlyList<SiegeEvent.SiegeEngineConstructionProgress>) siegeEventSide.SiegeEngines.DeployedRangedSiegeEngines).FindIndex<SiegeEvent.SiegeEngineConstructionProgress>((Func<SiegeEvent.SiegeEngineConstructionProgress, bool>) (engine => engine == attackerSiegeEngine)) : ((IReadOnlyList<SiegeEvent.SiegeEngineConstructionProgress>) siegeEventSide.SiegeEngines.DeployedMeleeSiegeEngines).FindIndex<SiegeEvent.SiegeEngineConstructionProgress>((Func<SiegeEvent.SiegeEngineConstructionProgress, bool>) (engine => engine == attackerSiegeEngine));
              SiegeBombardTargets targetType;
              int targetIndex;
              siegeEventSide.GetAttackTarget(siegeEventSide, attackerSiegeEngine.SiegeEngine, num, out targetType, out targetIndex);
              if (targetType != SiegeBombardTargets.None)
              {
                rangedSiegeEngine.OnFireDecisionTaken(this, siegeEventSide.BattleSide, targetIndex, targetType);
                bool hitSuccessful = (double) MBRandom.RandomFloat < (double) Campaign.Current.Models.SiegeEventModel.GetSiegeEngineHitChance(siegeEngine, siegeEventSide.BattleSide, targetType, this.BesiegedSettlement.Town);
                SiegeEvent.SiegeEngineConstructionProgress targetSiegeEngine = (SiegeEvent.SiegeEngineConstructionProgress) null;
                if (targetType == SiegeBombardTargets.RangedEngines)
                  targetSiegeEngine = siegeEngines.DeployedRangedSiegeEngines[targetIndex];
                SiegeEvent.SiegeEngineMissile missile = new SiegeEvent.SiegeEngineMissile(siegeEngine, num, targetType, targetIndex, targetSiegeEngine, rangedSiegeEngine.NextProjectileCollisionTime, CampaignTime.Now, hitSuccessful);
                siegeEventSide.AddSiegeEngineMissile(missile);
              }
              else
                rangedSiegeEngine.Hold();
            }
          }
        }
      }
    }

    private float GetDistanceBetweenTwoRangedEngine(int attackerSlotIndex, int defenderSlotIndex)
    {
      return (float) ((double) MathF.Abs(attackerSlotIndex - defenderSlotIndex) * 1.0 + 3.0);
    }

    private float PriorityCalculationForEngines(float distance) => 7f - distance;

    public void FindAttackableRangedEngineWithHighestPriority(
      ISiegeEventSide siegeEventSide,
      int attackerSlotIndex,
      out int targetIndex,
      out float targetPriority)
    {
      targetIndex = -1;
      targetPriority = 0.0f;
      float num1 = 9999f;
      SiegeEvent.SiegeEngineConstructionProgress[] rangedSiegeEngines = this.GetSiegeEventSide(siegeEventSide.BattleSide.GetOppositeSide()).SiegeEngines.DeployedRangedSiegeEngines;
      for (int defenderSlotIndex = 0; defenderSlotIndex < rangedSiegeEngines.Length; ++defenderSlotIndex)
      {
        SiegeEvent.SiegeEngineConstructionProgress constructionProgress = rangedSiegeEngines[defenderSlotIndex];
        if ((constructionProgress == null || !constructionProgress.IsActive ? 0 : ((double) constructionProgress.Hitpoints > 0.0 ? 1 : 0)) != 0)
        {
          float betweenTwoRangedEngine = this.GetDistanceBetweenTwoRangedEngine(attackerSlotIndex, defenderSlotIndex);
          float num2 = this.PriorityCalculationForEngines(betweenTwoRangedEngine);
          if ((double) num2 > (double) targetPriority || (double) MathF.Abs(num2 - targetPriority) < 9.9999997473787516E-05 && (double) num1 > (double) betweenTwoRangedEngine)
          {
            targetIndex = defenderSlotIndex;
            targetPriority = num2;
            num1 = betweenTwoRangedEngine;
          }
        }
      }
    }

    private void OnSiegeEngineDestroyed(
      ISiegeEventSide siegeEventSide,
      SiegeEvent.SiegeEngineConstructionProgress siegeEngine)
    {
      int ofDeployedEngine = siegeEventSide.SiegeEngines.FindDeploymentIndexOfDeployedEngine(siegeEngine);
      if (ofDeployedEngine == -1)
        siegeEventSide.SiegeEngines.RemovedSiegeEngineFromReservedSiegeEngines(siegeEngine);
      else
        this.DoSiegeAction(siegeEventSide, SiegeStrategyActionModel.SiegeAction.RemoveDeployedSiegeEngine, siegeEngine.SiegeEngine, ofDeployedEngine, -1);
      this.BesiegedSettlement.Party.SetVisualAsDirty();
      CampaignEventDispatcher.Instance.OnSiegeEngineDestroyed(this.BesiegerCamp.LeaderParty, this.BesiegedSettlement, siegeEventSide.BattleSide, siegeEngine.SiegeEngine);
    }

    private void BombardHitEngine(
      ISiegeEventSide siegeEventSide,
      SiegeEngineType attackerEngineType,
      SiegeEvent.SiegeEngineConstructionProgress damagedEngine)
    {
      ISiegeEventSide siegeEventSide1 = this.GetSiegeEventSide(siegeEventSide.BattleSide.GetOppositeSide());
      float siegeEngineDamage = Campaign.Current.Models.SiegeEventModel.GetSiegeEngineDamage(this, siegeEventSide.BattleSide, attackerEngineType, SiegeBombardTargets.RangedEngines);
      damagedEngine.SetHitpoints(damagedEngine.Hitpoints - siegeEngineDamage);
      CampaignEventDispatcher.Instance.OnSiegeBombardmentHit(this.BesiegerCamp.LeaderParty, this.BesiegedSettlement, siegeEventSide.BattleSide, attackerEngineType, SiegeBombardTargets.RangedEngines);
      if ((double) damagedEngine.Hitpoints <= 0.0)
        this.OnSiegeEngineDestroyed(siegeEventSide1, damagedEngine);
      if (!this.IsPlayerSiegeEvent)
        return;
      Debug.Print(this.BesiegedSettlement.Name.ToString() + " - " + siegeEventSide.BattleSide.ToString() + " " + (object) attackerEngineType.Name + " hit the enemy ranged siege engine(" + (object) damagedEngine.SiegeEngine.Name + ") for " + (object) siegeEngineDamage, color: Debug.DebugColor.Purple, debugFilter: 137438953472UL);
    }

    public class RangedSiegeEngine
    {
      [SaveableField(1)]
      public readonly SiegeEngineType EngineType;

      internal static void AutoGeneratedStaticCollectObjectsRangedSiegeEngine(
        object o,
        List<object> collectedObjects)
      {
        ((SiegeEvent.RangedSiegeEngine) o).AutoGeneratedInstanceCollectObjects(collectedObjects);
      }

      protected virtual void AutoGeneratedInstanceCollectObjects(List<object> collectedObjects)
      {
        collectedObjects.Add((object) this.EngineType);
        CampaignTime.AutoGeneratedStaticCollectObjectsCampaignTime((object) this.NextTimeEngineCanBombard, collectedObjects);
        CampaignTime.AutoGeneratedStaticCollectObjectsCampaignTime((object) this.LastBombardTime, collectedObjects);
      }

      internal static object AutoGeneratedGetMemberValueNextTimeEngineCanBombard(object o)
      {
        return (object) ((SiegeEvent.RangedSiegeEngine) o).NextTimeEngineCanBombard;
      }

      internal static object AutoGeneratedGetMemberValueAlreadyFired(object o)
      {
        return (object) ((SiegeEvent.RangedSiegeEngine) o).AlreadyFired;
      }

      internal static object AutoGeneratedGetMemberValueCurrentTargetType(object o)
      {
        return (object) ((SiegeEvent.RangedSiegeEngine) o).CurrentTargetType;
      }

      internal static object AutoGeneratedGetMemberValueCurrentTargetIndex(object o)
      {
        return (object) ((SiegeEvent.RangedSiegeEngine) o).CurrentTargetIndex;
      }

      internal static object AutoGeneratedGetMemberValuePreviousDamagedTargetType(object o)
      {
        return (object) ((SiegeEvent.RangedSiegeEngine) o).PreviousDamagedTargetType;
      }

      internal static object AutoGeneratedGetMemberValuePreviousTargetIndex(object o)
      {
        return (object) ((SiegeEvent.RangedSiegeEngine) o).PreviousTargetIndex;
      }

      internal static object AutoGeneratedGetMemberValueLastBombardTime(object o)
      {
        return (object) ((SiegeEvent.RangedSiegeEngine) o).LastBombardTime;
      }

      internal static object AutoGeneratedGetMemberValueEngineType(object o)
      {
        return (object) ((SiegeEvent.RangedSiegeEngine) o).EngineType;
      }

      [SaveableProperty(2)]
      public CampaignTime NextTimeEngineCanBombard { get; private set; }

      [SaveableProperty(3)]
      public bool AlreadyFired { get; private set; }

      [SaveableProperty(4)]
      public SiegeBombardTargets CurrentTargetType { get; private set; }

      [SaveableProperty(5)]
      public int CurrentTargetIndex { get; private set; }

      [SaveableProperty(6)]
      public SiegeBombardTargets PreviousDamagedTargetType { get; private set; }

      [SaveableProperty(7)]
      public int PreviousTargetIndex { get; private set; }

      [SaveableProperty(8)]
      public CampaignTime LastBombardTime { get; private set; }

      public CampaignTime NextProjectileCollisionTime
      {
        get => this.LastBombardTime.IsFuture ? CampaignTime.Never : this.NextTimeEngineCanBombard;
      }

      public bool IsReadyToFire => this.NextTimeEngineCanBombard.IsPast;

      public RangedSiegeEngine(SiegeEngineType engineType, ISiegeEventSide siegeSide)
      {
        this.EngineType = engineType;
        this.CurrentTargetType = SiegeBombardTargets.None;
        this.CurrentTargetIndex = -1;
        this.PreviousDamagedTargetType = SiegeBombardTargets.None;
        this.PreviousTargetIndex = -1;
        this.AlreadyFired = false;
        this.LastBombardTime = CampaignTime.Never;
        this.CalculateNextFireTime(siegeSide.SiegeEvent, siegeSide.BattleSide);
      }

      public void Hold()
      {
        this.CurrentTargetType = SiegeBombardTargets.None;
        this.CurrentTargetIndex = -1;
      }

      public void Reload() => this.AlreadyFired = false;

      public void OnFireDecisionTaken(
        SiegeEvent siegeEvent,
        BattleSideEnum battleSide,
        int targetSlotIndex,
        SiegeBombardTargets targetType)
      {
        this.PreviousDamagedTargetType = this.CurrentTargetType;
        this.PreviousTargetIndex = this.CurrentTargetIndex;
        this.CurrentTargetIndex = targetSlotIndex;
        this.CurrentTargetType = targetType;
        this.AlreadyFired = true;
        this.LastBombardTime = CampaignTime.Now;
        this.CalculateNextFireTime(siegeEvent, battleSide);
      }

      private void CalculateNextFireTime(SiegeEvent siegeEvent, BattleSideEnum battleSide)
      {
        this.NextTimeEngineCanBombard = CampaignTime.Now + CampaignTime.Minutes((long) Campaign.Current.Models.SiegeEventModel.GetRangedSiegeEngineReloadTime(siegeEvent, battleSide, this.EngineType));
      }
    }

    public class SiegeEngineConstructionProgress
    {
      [SaveableField(1)]
      public readonly SiegeEngineType SiegeEngine;

      internal static void AutoGeneratedStaticCollectObjectsSiegeEngineConstructionProgress(
        object o,
        List<object> collectedObjects)
      {
        ((SiegeEvent.SiegeEngineConstructionProgress) o).AutoGeneratedInstanceCollectObjects(collectedObjects);
      }

      protected virtual void AutoGeneratedInstanceCollectObjects(List<object> collectedObjects)
      {
        collectedObjects.Add((object) this.SiegeEngine);
        collectedObjects.Add((object) this.RangedSiegeEngine);
      }

      internal static object AutoGeneratedGetMemberValueHitpoints(object o)
      {
        return (object) ((SiegeEvent.SiegeEngineConstructionProgress) o).Hitpoints;
      }

      internal static object AutoGeneratedGetMemberValueProgress(object o)
      {
        return (object) ((SiegeEvent.SiegeEngineConstructionProgress) o).Progress;
      }

      internal static object AutoGeneratedGetMemberValueRangedSiegeEngine(object o)
      {
        return (object) ((SiegeEvent.SiegeEngineConstructionProgress) o).RangedSiegeEngine;
      }

      internal static object AutoGeneratedGetMemberValueRedeploymentProgress(object o)
      {
        return (object) ((SiegeEvent.SiegeEngineConstructionProgress) o).RedeploymentProgress;
      }

      internal static object AutoGeneratedGetMemberValueMaxHitPoints(object o)
      {
        return (object) ((SiegeEvent.SiegeEngineConstructionProgress) o).MaxHitPoints;
      }

      internal static object AutoGeneratedGetMemberValueSiegeEngine(object o)
      {
        return (object) ((SiegeEvent.SiegeEngineConstructionProgress) o).SiegeEngine;
      }

      public bool IsActive => this.IsConstructed && !this.IsBeingRedeployed;

      [SaveableProperty(3)]
      public float Hitpoints { get; private set; }

      [SaveableProperty(4)]
      public float Progress { get; private set; }

      [SaveableProperty(5)]
      public SiegeEvent.RangedSiegeEngine RangedSiegeEngine { get; private set; }

      [SaveableProperty(6)]
      public float RedeploymentProgress { get; private set; }

      [SaveableProperty(7)]
      public float MaxHitPoints { get; private set; }

      public bool IsConstructed => (double) this.Progress >= 1.0;

      public bool IsBeingRedeployed => (double) this.RedeploymentProgress < 1.0;

      public SiegeEngineConstructionProgress(
        SiegeEngineType siegeEngine,
        float progress,
        float maxHitPoints)
      {
        this.SiegeEngine = siegeEngine;
        this.Progress = progress;
        this.RedeploymentProgress = 1f;
        this.RangedSiegeEngine = (SiegeEvent.RangedSiegeEngine) null;
        this.MaxHitPoints = maxHitPoints;
        this.Hitpoints = this.MaxHitPoints;
      }

      public void SetRedeploymentProgress(float redeploymentProgress)
      {
        this.RedeploymentProgress = redeploymentProgress;
      }

      public void SetHitpoints(float hitPoints) => this.Hitpoints = hitPoints;

      public void SetProgress(float progress) => this.Progress = progress;

      public void SetRangedSiegeEngine(SiegeEvent.RangedSiegeEngine rangedSiegeEngine)
      {
        this.RangedSiegeEngine = rangedSiegeEngine;
      }
    }

    public class SiegeEnginesContainer
    {
      public const int MaximumAttackerMeleeSiegeEngineCount = 3;
      public const int MaximumAttackerRangedSiegeEngineCount = 4;
      public const int MaximumDefenderMeleeSiegeEngineCount = 0;
      public const int MaximumDefenderRangedSiegeEngineCount = 4;
      [SaveableField(1)]
      public readonly SiegeEvent.SiegeEngineConstructionProgress SiegePreparations;
      [SaveableField(2)]
      private readonly MBList<SiegeEvent.SiegeEngineConstructionProgress> _deployedSiegeEngines;
      [SaveableField(3)]
      private readonly MBList<SiegeEvent.SiegeEngineConstructionProgress> _reservedSiegeEngines;
      [SaveableField(4)]
      public readonly SiegeEvent.SiegeEngineConstructionProgress[] DeployedRangedSiegeEngines;
      [SaveableField(5)]
      public readonly SiegeEvent.SiegeEngineConstructionProgress[] DeployedMeleeSiegeEngines;
      [SaveableField(6)]
      private readonly Dictionary<SiegeEngineType, int> _deployedSiegeEngineTypesCount;
      [SaveableField(7)]
      private readonly Dictionary<SiegeEngineType, int> _reservedSiegeEngineTypesCount;
      [SaveableField(8)]
      private readonly MBList<SiegeEvent.SiegeEnginesContainer.RemovedSiegeEngine> _removedSiegeEngines;

      internal static void AutoGeneratedStaticCollectObjectsSiegeEnginesContainer(
        object o,
        List<object> collectedObjects)
      {
        ((SiegeEvent.SiegeEnginesContainer) o).AutoGeneratedInstanceCollectObjects(collectedObjects);
      }

      protected virtual void AutoGeneratedInstanceCollectObjects(List<object> collectedObjects)
      {
        collectedObjects.Add((object) this.SiegePreparations);
        collectedObjects.Add((object) this.DeployedRangedSiegeEngines);
        collectedObjects.Add((object) this.DeployedMeleeSiegeEngines);
        collectedObjects.Add((object) this._deployedSiegeEngines);
        collectedObjects.Add((object) this._reservedSiegeEngines);
        collectedObjects.Add((object) this._deployedSiegeEngineTypesCount);
        collectedObjects.Add((object) this._reservedSiegeEngineTypesCount);
        collectedObjects.Add((object) this._removedSiegeEngines);
      }

      internal static object AutoGeneratedGetMemberValueSiegePreparations(object o)
      {
        return (object) ((SiegeEvent.SiegeEnginesContainer) o).SiegePreparations;
      }

      internal static object AutoGeneratedGetMemberValueDeployedRangedSiegeEngines(object o)
      {
        return (object) ((SiegeEvent.SiegeEnginesContainer) o).DeployedRangedSiegeEngines;
      }

      internal static object AutoGeneratedGetMemberValueDeployedMeleeSiegeEngines(object o)
      {
        return (object) ((SiegeEvent.SiegeEnginesContainer) o).DeployedMeleeSiegeEngines;
      }

      internal static object AutoGeneratedGetMemberValue_deployedSiegeEngines(object o)
      {
        return (object) ((SiegeEvent.SiegeEnginesContainer) o)._deployedSiegeEngines;
      }

      internal static object AutoGeneratedGetMemberValue_reservedSiegeEngines(object o)
      {
        return (object) ((SiegeEvent.SiegeEnginesContainer) o)._reservedSiegeEngines;
      }

      internal static object AutoGeneratedGetMemberValue_deployedSiegeEngineTypesCount(object o)
      {
        return (object) ((SiegeEvent.SiegeEnginesContainer) o)._deployedSiegeEngineTypesCount;
      }

      internal static object AutoGeneratedGetMemberValue_reservedSiegeEngineTypesCount(object o)
      {
        return (object) ((SiegeEvent.SiegeEnginesContainer) o)._reservedSiegeEngineTypesCount;
      }

      internal static object AutoGeneratedGetMemberValue_removedSiegeEngines(object o)
      {
        return (object) ((SiegeEvent.SiegeEnginesContainer) o)._removedSiegeEngines;
      }

      public MBReadOnlyList<SiegeEvent.SiegeEngineConstructionProgress> DeployedSiegeEngines
      {
        get
        {
          return (MBReadOnlyList<SiegeEvent.SiegeEngineConstructionProgress>) this._deployedSiegeEngines;
        }
      }

      public MBReadOnlyList<SiegeEvent.SiegeEngineConstructionProgress> ReservedSiegeEngines
      {
        get
        {
          return (MBReadOnlyList<SiegeEvent.SiegeEngineConstructionProgress>) this._reservedSiegeEngines;
        }
      }

      public MBReadOnlyDictionary<SiegeEngineType, int> DeployedSiegeEngineTypesCount { get; private set; }

      public MBReadOnlyDictionary<SiegeEngineType, int> ReservedSiegeEngineTypesCount { get; private set; }

      public MBReadOnlyList<SiegeEvent.SiegeEnginesContainer.RemovedSiegeEngine> RemovedSiegeEngines
      {
        get
        {
          return (MBReadOnlyList<SiegeEvent.SiegeEnginesContainer.RemovedSiegeEngine>) this._removedSiegeEngines;
        }
      }

      [LoadInitializationCallback]
      private void OnLoad(MetaData metaData)
      {
        this.DeployedSiegeEngineTypesCount = new MBReadOnlyDictionary<SiegeEngineType, int>(this._deployedSiegeEngineTypesCount);
        this.ReservedSiegeEngineTypesCount = new MBReadOnlyDictionary<SiegeEngineType, int>(this._reservedSiegeEngineTypesCount);
        this.RefreshDeployedCounts();
        this.RefreshReservedCounts();
      }

      public IEnumerable<SiegeEvent.SiegeEngineConstructionProgress> AllSiegeEngines()
      {
        if (this.SiegePreparations != null)
          yield return this.SiegePreparations;
        foreach (SiegeEvent.SiegeEngineConstructionProgress deployedSiegeEngine in (List<SiegeEvent.SiegeEngineConstructionProgress>) this._deployedSiegeEngines)
          yield return deployedSiegeEngine;
        foreach (SiegeEvent.SiegeEngineConstructionProgress reservedSiegeEngine in (List<SiegeEvent.SiegeEngineConstructionProgress>) this._reservedSiegeEngines)
          yield return reservedSiegeEngine;
      }

      public SiegeEnginesContainer(
        BattleSideEnum side,
        SiegeEvent.SiegeEngineConstructionProgress siegePreparations)
      {
        this.SiegePreparations = siegePreparations;
        switch (side)
        {
          case BattleSideEnum.Defender:
            this._deployedSiegeEngines = new MBList<SiegeEvent.SiegeEngineConstructionProgress>(4);
            this.DeployedRangedSiegeEngines = new SiegeEvent.SiegeEngineConstructionProgress[4];
            this.DeployedMeleeSiegeEngines = new SiegeEvent.SiegeEngineConstructionProgress[0];
            break;
          case BattleSideEnum.Attacker:
            this._deployedSiegeEngines = new MBList<SiegeEvent.SiegeEngineConstructionProgress>(4);
            this.DeployedRangedSiegeEngines = new SiegeEvent.SiegeEngineConstructionProgress[4];
            this.DeployedMeleeSiegeEngines = new SiegeEvent.SiegeEngineConstructionProgress[3];
            break;
          default:
            Debug.FailedAssert("Invalid side", "C:\\Develop\\MB3\\Source\\Bannerlord\\TaleWorlds.CampaignSystem\\Siege\\SiegeEvent.cs", ".ctor", 254);
            break;
        }
        this._deployedSiegeEngineTypesCount = new Dictionary<SiegeEngineType, int>();
        this.DeployedSiegeEngineTypesCount = new MBReadOnlyDictionary<SiegeEngineType, int>(this._deployedSiegeEngineTypesCount);
        this._reservedSiegeEngines = new MBList<SiegeEvent.SiegeEngineConstructionProgress>();
        this._reservedSiegeEngineTypesCount = new Dictionary<SiegeEngineType, int>();
        this.ReservedSiegeEngineTypesCount = new MBReadOnlyDictionary<SiegeEngineType, int>(this._reservedSiegeEngineTypesCount);
        this._removedSiegeEngines = new MBList<SiegeEvent.SiegeEnginesContainer.RemovedSiegeEngine>();
      }

      public void AddPrebuiltEngineToReserve(
        SiegeEvent.SiegeEngineConstructionProgress siegeEngine)
      {
        this._reservedSiegeEngines.Add(siegeEngine);
        siegeEngine.SetProgress(1f);
        siegeEngine.SetRedeploymentProgress(0.0f);
        this.RefreshReservedCounts();
      }

      public void DeploySiegeEngineAtIndex(
        SiegeEvent.SiegeEngineConstructionProgress siegeEngine,
        int index)
      {
        SiegeEvent.SiegeEngineConstructionProgress[] constructionProgressArray = siegeEngine.SiegeEngine.IsRanged ? this.DeployedRangedSiegeEngines : this.DeployedMeleeSiegeEngines;
        SiegeEvent.SiegeEngineConstructionProgress constructionProgress = constructionProgressArray[index];
        if (constructionProgress != null)
        {
          this._deployedSiegeEngines.Remove(constructionProgress);
          this._reservedSiegeEngines.Add(constructionProgress);
          constructionProgress.SetRedeploymentProgress(0.0f);
        }
        this._reservedSiegeEngines.Remove(siegeEngine);
        this.RefreshReservedCounts();
        constructionProgressArray[index] = siegeEngine;
        this._deployedSiegeEngines.Add(siegeEngine);
        this.RefreshDeployedCounts();
      }

      public void RemoveDeployedSiegeEngine(int index, bool isRanged, bool moveToReserve)
      {
        SiegeEvent.SiegeEngineConstructionProgress[] constructionProgressArray = isRanged ? this.DeployedRangedSiegeEngines : this.DeployedMeleeSiegeEngines;
        SiegeEvent.SiegeEngineConstructionProgress constructionProgress = constructionProgressArray[index];
        if (constructionProgress == null)
          return;
        if (moveToReserve)
        {
          this._reservedSiegeEngines.Add(constructionProgress);
          this.RefreshReservedCounts();
          constructionProgress.SetRedeploymentProgress(0.0f);
        }
        this._deployedSiegeEngines.Remove(constructionProgress);
        this.RefreshDeployedCounts();
        constructionProgressArray[index] = (SiegeEvent.SiegeEngineConstructionProgress) null;
      }

      public bool RemovedSiegeEngineFromReservedSiegeEngines(
        SiegeEvent.SiegeEngineConstructionProgress siegeEngine)
      {
        int num = this._reservedSiegeEngines.Remove(siegeEngine) ? 1 : 0;
        if (num == 0)
          return num != 0;
        this.RefreshReservedCounts();
        return num != 0;
      }

      public int FindDeploymentIndexOfDeployedEngine(
        SiegeEvent.SiegeEngineConstructionProgress deployedEngine)
      {
        return deployedEngine.SiegeEngine.IsRanged ? ((IReadOnlyList<SiegeEvent.SiegeEngineConstructionProgress>) this.DeployedRangedSiegeEngines).FindIndex<SiegeEvent.SiegeEngineConstructionProgress>((Func<SiegeEvent.SiegeEngineConstructionProgress, bool>) (engine => engine == deployedEngine)) : ((IReadOnlyList<SiegeEvent.SiegeEngineConstructionProgress>) this.DeployedMeleeSiegeEngines).FindIndex<SiegeEvent.SiegeEngineConstructionProgress>((Func<SiegeEvent.SiegeEngineConstructionProgress, bool>) (engine => engine == deployedEngine));
      }

      public bool ClearRemovedEnginesIfNecessary()
      {
        return this._removedSiegeEngines.RemoveAll((Predicate<SiegeEvent.SiegeEnginesContainer.RemovedSiegeEngine>) (engine => !engine.RemovalTime.IsFuture)) > 0;
      }

      private void RefreshDeployedCounts()
      {
        this._deployedSiegeEngineTypesCount.Clear();
        foreach (SiegeEvent.SiegeEngineConstructionProgress deployedSiegeEngine in (List<SiegeEvent.SiegeEngineConstructionProgress>) this.DeployedSiegeEngines)
        {
          SiegeEngineType siegeEngine = deployedSiegeEngine.SiegeEngine;
          int num;
          if (this._deployedSiegeEngineTypesCount.TryGetValue(siegeEngine, out num))
            this._deployedSiegeEngineTypesCount[siegeEngine] = num + 1;
          else
            this._deployedSiegeEngineTypesCount.Add(siegeEngine, 1);
        }
      }

      private void RefreshReservedCounts()
      {
        this._reservedSiegeEngineTypesCount.Clear();
        foreach (SiegeEvent.SiegeEngineConstructionProgress reservedSiegeEngine in (List<SiegeEvent.SiegeEngineConstructionProgress>) this.ReservedSiegeEngines)
        {
          SiegeEngineType siegeEngine = reservedSiegeEngine.SiegeEngine;
          int num;
          if (this._reservedSiegeEngineTypesCount.TryGetValue(siegeEngine, out num))
            this._reservedSiegeEngineTypesCount[siegeEngine] = num + 1;
          else
            this._reservedSiegeEngineTypesCount.Add(siegeEngine, 1);
        }
      }

      public class RemovedSiegeEngine
      {
        [SaveableField(1)]
        public readonly SiegeEvent.SiegeEngineConstructionProgress SiegeEngine;
        [SaveableField(2)]
        public readonly CampaignTime RemovalTime;
        [SaveableField(3)]
        public readonly int SlotIndex;

        internal static void AutoGeneratedStaticCollectObjectsRemovedSiegeEngine(
          object o,
          List<object> collectedObjects)
        {
          ((SiegeEvent.SiegeEnginesContainer.RemovedSiegeEngine) o).AutoGeneratedInstanceCollectObjects(collectedObjects);
        }

        protected virtual void AutoGeneratedInstanceCollectObjects(List<object> collectedObjects)
        {
          collectedObjects.Add((object) this.SiegeEngine);
          CampaignTime.AutoGeneratedStaticCollectObjectsCampaignTime((object) this.RemovalTime, collectedObjects);
        }

        internal static object AutoGeneratedGetMemberValueSiegeEngine(object o)
        {
          return (object) ((SiegeEvent.SiegeEnginesContainer.RemovedSiegeEngine) o).SiegeEngine;
        }

        internal static object AutoGeneratedGetMemberValueRemovalTime(object o)
        {
          return (object) ((SiegeEvent.SiegeEnginesContainer.RemovedSiegeEngine) o).RemovalTime;
        }

        internal static object AutoGeneratedGetMemberValueSlotIndex(object o)
        {
          return (object) ((SiegeEvent.SiegeEnginesContainer.RemovedSiegeEngine) o).SlotIndex;
        }

        public RemovedSiegeEngine(
          SiegeEvent.SiegeEngineConstructionProgress siegeEngine,
          CampaignTime removalTime,
          int slotIndex)
        {
          this.SiegeEngine = siegeEngine;
          this.RemovalTime = removalTime;
          this.SlotIndex = slotIndex;
        }
      }
    }

    public class SiegeEngineMissile
    {
      [SaveableField(1)]
      public readonly SiegeEngineType ShooterSiegeEngineType;
      [SaveableField(2)]
      public readonly int ShooterSlotIndex;
      [SaveableField(3)]
      public readonly SiegeBombardTargets TargetType;
      [SaveableField(4)]
      public readonly int TargetSlotIndex;
      [SaveableField(5)]
      public readonly SiegeEvent.SiegeEngineConstructionProgress TargetSiegeEngine;
      [SaveableField(6)]
      public readonly bool HitSuccessful;
      [SaveableField(7)]
      public readonly CampaignTime CollisionTime;
      [SaveableField(8)]
      public readonly CampaignTime FireDecisionTime;

      internal static void AutoGeneratedStaticCollectObjectsSiegeEngineMissile(
        object o,
        List<object> collectedObjects)
      {
        ((SiegeEvent.SiegeEngineMissile) o).AutoGeneratedInstanceCollectObjects(collectedObjects);
      }

      protected virtual void AutoGeneratedInstanceCollectObjects(List<object> collectedObjects)
      {
        collectedObjects.Add((object) this.ShooterSiegeEngineType);
        collectedObjects.Add((object) this.TargetSiegeEngine);
        CampaignTime.AutoGeneratedStaticCollectObjectsCampaignTime((object) this.CollisionTime, collectedObjects);
        CampaignTime.AutoGeneratedStaticCollectObjectsCampaignTime((object) this.FireDecisionTime, collectedObjects);
      }

      internal static object AutoGeneratedGetMemberValueShooterSiegeEngineType(object o)
      {
        return (object) ((SiegeEvent.SiegeEngineMissile) o).ShooterSiegeEngineType;
      }

      internal static object AutoGeneratedGetMemberValueShooterSlotIndex(object o)
      {
        return (object) ((SiegeEvent.SiegeEngineMissile) o).ShooterSlotIndex;
      }

      internal static object AutoGeneratedGetMemberValueTargetType(object o)
      {
        return (object) ((SiegeEvent.SiegeEngineMissile) o).TargetType;
      }

      internal static object AutoGeneratedGetMemberValueTargetSlotIndex(object o)
      {
        return (object) ((SiegeEvent.SiegeEngineMissile) o).TargetSlotIndex;
      }

      internal static object AutoGeneratedGetMemberValueTargetSiegeEngine(object o)
      {
        return (object) ((SiegeEvent.SiegeEngineMissile) o).TargetSiegeEngine;
      }

      internal static object AutoGeneratedGetMemberValueHitSuccessful(object o)
      {
        return (object) ((SiegeEvent.SiegeEngineMissile) o).HitSuccessful;
      }

      internal static object AutoGeneratedGetMemberValueCollisionTime(object o)
      {
        return (object) ((SiegeEvent.SiegeEngineMissile) o).CollisionTime;
      }

      internal static object AutoGeneratedGetMemberValueFireDecisionTime(object o)
      {
        return (object) ((SiegeEvent.SiegeEngineMissile) o).FireDecisionTime;
      }

      public SiegeEngineMissile(
        SiegeEngineType shooterSiegeEngineType,
        int shooterSlotIndex,
        SiegeBombardTargets targetType,
        int targetSlotIndex,
        SiegeEvent.SiegeEngineConstructionProgress targetSiegeEngine,
        CampaignTime collisionTime,
        CampaignTime fireTime,
        bool hitSuccessful)
      {
        this.ShooterSiegeEngineType = shooterSiegeEngineType;
        this.ShooterSlotIndex = shooterSlotIndex;
        this.TargetType = targetType;
        this.TargetSlotIndex = targetSlotIndex;
        this.TargetSiegeEngine = targetSiegeEngine;
        this.CollisionTime = collisionTime;
        this.FireDecisionTime = fireTime;
        this.HitSuccessful = hitSuccessful;
      }
    }
  }
}
